﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.IO;

namespace OutlookCalendarCleaner
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private Outlook.Application olApp;
        private const string specialChar = "\x2";
        int foundCnt = 0;
        int totalCnt = 0;
        int fixCnt = 0;
        string logFileName = "";
        int polePos = 0;

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                // init
                polePos = 10;
                listBox1.Items.Clear();
                Label1.Text = "...";
                Label2.Text = "...";
                Label3.Text = "...";
                foundCnt = 0;
                totalCnt = 0;
                fixCnt = 0;

                // open outlook and have user select calendar
                Outlook.Folder folder = null;
                try
                {
                    polePos = 20;
                    olApp = new Outlook.Application();
                    folder = (Outlook.Folder)olApp.Session.PickFolder();
                    if (folder == null)
                        return;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to initialize Outlook or select folder.\n\n" + ex.ToString());
                    return;
                }

                polePos = 30;
                // was the item the user selected a calendar folder?
                if (folder.DefaultItemType == Outlook.OlItemType.olAppointmentItem)
                {
                    // set filename
                    logFileName = "SCAN" + DateTime.Now.ToString().Replace("/", "-").Replace(":", ".") + ".txt";
                    // log to user
                    logIt("Started at " + DateTime.Now.ToString());
                    logIt("Writing to log file: " + logFileName);
                    if (checkBox1.Checked)
                        logIt("The CLEAN option is [ON].");
                    else
                        logIt("The CLEAN option is [OFF].");
                    logIt("Selected folder: " + folder.FolderPath);
                    // setup
                    Label1.Text = "1";
                    Label2.Text = folder.Items.Count.ToString();
                    button1.Enabled = false;
                    checkBox1.Enabled = false;
                    polePos = 40;
                    // loop though all the folder items
                    for (int i = 1; i <= folder.Items.Count; i++)
                    {
                        // set the object
                        object o = null;
                        try
                        {
                            polePos = 50;
                            o = folder.Items[i];
                        }
                        catch
                        {
                            // it appears that something we have corrupt items
                            // this may lead to other problems -- unknow -- but
                            // in order to proceed we need to skip it. Log it
                            // and continue on...
                            polePos = 60;
                            logIt("ERROR: Item#" + i.ToString() + " is corrupt. Skipping.");
                            continue;
                        }
                        totalCnt++;
                        Label1.Text = totalCnt.ToString();
                        // refresh every 30 items to speed up, reduce flashing
                        // and make it look cleaner
                        if (totalCnt % 30 == 0)
                            this.Refresh(); Application.DoEvents();

                        // see if it is a meeting or appointment
                        polePos = 60;
                        Outlook.AppointmentItem apItem = null;
                        Outlook.MeetingItem mtItem = null;
                        try
                        {
                            polePos = 70;
                            apItem = o as Outlook.AppointmentItem;
                            mtItem = o as Outlook.MeetingItem;
                        }
                        catch
                        {
                            polePos = 80;
                            // log it for posterity... if we get a full folder of these
                            // then maybe there is some type of corruption
                            logIt("Exception occurred trying to cast a Meeting/Appointment item.");
                        } // swallow the exception -- items will remain null, we will skip to next

                        // if neither -- next
                        if (apItem == null &&  mtItem == null)
                            continue;

                        // now check to see if appointment and ahs special char
                        polePos = 90;
                        if (apItem != null && 
                            apItem.Subject != null && 
                            apItem.Subject.Contains(specialChar))
                        {
                            // yes -- count and log it
                            polePos = 100;
                            string subject = mtItem.Subject;
                            string date = null;
                            try
                            {
                                polePos = 110;
                                date = apItem.Start.ToString();
                            }
                            catch
                            {
                                date = "[DATE-NULL]";
                            }
                            logIt("[" + totalCnt.ToString() + "] APT: " + subject + " @ " + date, true);
                            // clean?
                            if (checkBox1.Checked)
                            {
                                try
                                {
                                    polePos = 120;
                                    apItem.Subject = apItem.Subject.Replace(specialChar, " ");
                                    apItem.Save();
                                    logIt("Cleaned: " + apItem.Subject);
                                    fixCnt++;
                                }
                                catch
                                {
                                    // log failure -- but continue
                                    logIt("Unable to change/save item: " + apItem.Subject);
                                }
                            }
                        }
                        else if (mtItem != null && 
                                 mtItem.Subject!= null && 
                                 mtItem.Subject.Contains(specialChar))
                        {
                            polePos = 130;
                            // yes -- count and log it
                            string subject = mtItem.Subject;
                            string date = null; 
                            try
                            {
                                polePos = 140;
                                date = mtItem.ReminderTime.ToString();
                            }
                            catch
                            {
                                date = "[DATE-NULL]";
                            }
                            logIt("[" + totalCnt.ToString() + "] MTG: " + subject + " @ " + date, true);
                            // clean?
                            if (checkBox1.Checked)
                            {
                                try
                                {
                                    polePos = 150;
                                    mtItem.Subject = mtItem.Subject.Replace(specialChar, " ");
                                    mtItem.Save();
                                    logIt("Cleaned: " + mtItem.Subject);
                                    fixCnt++;
                                }
                                catch
                                {
                                    // log failure -- but continue
                                    logIt("Unable to change/save item: " + mtItem.Subject);
                                }
                            }
                        }
                        else if ((apItem!=null && apItem.Subject == null) || 
                                 (mtItem!=null && mtItem.Subject == null))
                        {
                            polePos = 160;
                            // yes -- count and log it
                            string date = null; 
                            try
                            {
                                polePos = 170;
                                if(apItem == null)
                                    date = mtItem.ReminderTime.ToString();
                                else
                                    date = apItem.Start.ToString();
                            }
                            catch
                            {
                                date = "[DATE-NULL]";
                            }
                            polePos = 180;
                            if(apItem == null)
                                logIt("[" + totalCnt.ToString() + "] MTG: [NULL-SUBJECT] @ " + date, true);
                            else
                                logIt("[" + totalCnt.ToString() + "] APT: [NULL-SUBJECT] @ " + date, true);
                            // clean?
                            if (checkBox1.Checked)
                            {
                                logIt("Unable to clean item @ " + date);
                            }
                        }
                    }
                    polePos = 190;
                    logIt("Scan complete!");
                    logIt("There were [" + totalCnt.ToString() + "] items scanned.");
                    logIt("There were [" + foundCnt.ToString() + "] items found.");
                    logIt("There were [" + fixCnt.ToString() + "] items fixed.");
                    button1.Enabled = true;
                    checkBox1.Enabled = true;
                }
                else
                {
                    MessageBox.Show("You must select a calendar folder.");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("An unhandled exception occurred [@" + polePos.ToString() + "]: \n" + ex.ToString());
                button1.Enabled = true;
                checkBox1.Enabled = true;
            }
        }

        private void logIt(string info, bool fFound = false)
        {
            // yes -- count
            if (fFound)
            {
                foundCnt++;
                Label3.Text = foundCnt.ToString();
                this.Refresh(); Application.DoEvents();
            }
            // update log
            listBox1.Items.Add(info);

            // write to log file
            string path = Application.StartupPath + "\\" + logFileName;
            StreamWriter sw = new StreamWriter(path, true);
            sw.WriteLine(info);
            sw.Close();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("Are you sure you want to correct metting/appointment items found? \n\n" +
                                              "As a precaution, please be sure to have a backup of the calendar " +
                                              "of the user before proceeding.", "Clean Calendar Items Found", 
                                              MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation);
            if (dr != System.Windows.Forms.DialogResult.Yes)
            {
                checkBox1.CheckedChanged -=new EventHandler(checkBox1_CheckedChanged);
                checkBox1.Checked = false;
                checkBox1.CheckedChanged += new EventHandler(checkBox1_CheckedChanged);
            }
        }
    }
}
